/********************************Copyright (c)**********************************\
**
**                   (c) Copyright 2021, Main, China, QD.
**                           All Rights Reserved
**
**                                 By(wo4fisher)
**                           http://www.wo4fisher.com
**
**----------------------------------文件信息------------------------------------
** 文件名称: bsp_GU12864.c
** 创建人员: wht
** 创建日期: 2021-08-07
** 文档描述: GU12864的驱动程序  使用8080时序
**
**----------------------------------版本信息------------------------------------
** 版本代号: V0.1
** 版本说明: 初始版本
**
**------------------------------------------------------------------------------
\********************************End of Head************************************/

#include "bsp_GU12864.h"


#define HIGH 1
#define LOW  0

#define GU_X_WIDTH 128
#define GU_Y_WIDTH 16

#define GU_WR_PIN P70  //WRITE 
#define GU_CD_PIN P71  //(C,/D)
#define GU_RD_PIN P72  //READ
#define GU_CS_PIN P73  // CS 
#define GU_DATA_PORT P1

#define GU_WRITE_SET()  GU_WR_PIN = HIGH
#define GU_WRITE_RESET()  GU_WR_PIN = LOW

#define GU_CD_SET()  GU_CD_PIN = HIGH //CMD
#define GU_CD_RESET() GU_CD_PIN = LOW //DATA

#define GU_READ_SET() GU_RD_PIN = HIGH
#define GU_READ_RESET() GU_RD_PIN = LOW

#define GU_CS_SET() GU_CS_PIN = HIGH
#define GU_CS_RESET() GU_CS_PIN = LOW

/**
 * [GU_WriteCmd 写命令]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param cmd [命令字节]
 */
void GU_WriteCmd(uint8 cmd)
{
	GU_CS_RESET();
	delayxus(1);
	GU_CD_SET();
	delayxus(1);
	GU_READ_SET();
	delayxus(1);
	GU_WRITE_RESET();
	delayxus(1);
	GU_DATA_PORT = cmd;
	delayxus(1);
	GU_WRITE_SET();
	delayxus(1);
	GU_CS_SET();
}

/**
 * [GU_WriteData 写数据]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param data8 [给屏的数据]
 */
void GU_WriteData(uint8 data8)
{
	GU_CS_RESET();
	delayxus(1);
	GU_CD_RESET();
	delayxus(1);
	GU_READ_SET();
	delayxus(1);
	GU_WRITE_RESET();
	delayxus(1);
	GU_DATA_PORT = data8;
	delayxus(1);
	GU_WRITE_SET();
	delayxus(1);
	GU_CS_SET();
	delayxus(1);
}
static uint8 GU_ReadData(void)
{
	uint8 temp;
	GU_CS_RESET();
	delayxus(1);
	GU_CD_SET();
	delayxus(1);
	GU_WRITE_SET();
	delayxus(1);
	GU_READ_RESET();
	delayxus(1);
	temp = GU_DATA_PORT;
	delayxus(1);
	GU_READ_SET();
	delayxus(1);
	GU_CS_SET();
	delayxus(1);
	return temp;
}
#define GU_CMD_READADDR 0XD4
/**
 * [GU_ReadAddr 读出当前地址]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param  x [保存x轴地址数据]
 * @param  y [保存y轴地址数据]
 * @return   [void]
 */
void GU_ReadAddr(uint8 * x, uint8 * y)
{
	GU_WriteCmd(GU_CMD_READADDR);
	*x = GU_ReadData();
	*y = GU_ReadData();
}

/**
 * [GU_Init 初始化]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 */
void GU_Init(void)
{
	uint8 i = 0;
	GU_WriteCmd(0X5F);
	pca_delay_ms(1);
	for (i = 0; i < 8; i++)
	{
		GU_WriteCmd(0X62);
		GU_WriteCmd(i);
		GU_WriteData(0xFF);
	}
	GU_Set_X_StartAddr(0);
	GU_SetAddrMode();
	GU_WriteCmd(0X24);//显示 ON/OFF0   0X08  L1;0X04  L0
	GU_WriteCmd(0X40);//显示 ON/OFF
	GU_Clear();
}
#define GU_CMD_SET_DISPLAY_ONOFF 0X20
// #define   GU_DISPLAY_ON      0X40
// #define   GU_DISPLAY_OFF     0X00
// #define   GU_DISPLAY_L1      0X08
// #define   GU_DISPLAY_L0      0X04
// #define   GU_DISPLAY_L0L1    0X0C
/**
 * [GU_DisplaySet 显示设置]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param LSel  [description]
 * @param onOff [description]
 */
void GU_DisplaySet(uint8 LSel, bit onOff)
{
	GU_WriteCmd(GU_CMD_SET_DISPLAY_ONOFF | LSel);
	GU_WriteCmd(onOff);
}
#define GU_CMD_SETLED 0X40
/**
 * [GU_SetLed 设置亮度 0~15 越小越亮]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param brightness [description]
 */
void GU_SetLed(uint8 brightness)
{
	GU_WriteCmd(GU_CMD_SETLED | brightness);
}
#define GU_CMD_SETDISAREA  0X50 //主要用于初始化
/**
 * [GU_SetDisArea 设置显示ON/OFF?]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 */
void GU_SetDisArea(void) //主要用于初始化
{
	GU_WriteCmd(GU_CMD_SETDISAREA | 0x0F);
}
#define GU_CMD_SETPOS 0X60
/**
 * [GU_SetPos 设置ram地址]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param x [0~127]
 * @param y [0~7]
 */
void GU_SetPos(uint8 x, uint8 y) //x:0~127;y:0~15
{
	GU_WriteCmd(GU_CMD_SETPOS | (1 << 2));
	GU_WriteCmd(x);
	GU_WriteCmd(GU_CMD_SETPOS );
	GU_WriteCmd(y);
}

#define GU_CMD_SETDISPLAYSTARTX  0X70  //暂时做到初始化，设定显示ram开始地址
#define GU_CMD_SETDISPLAYSTARTY  0XB0  // 没看懂
#define GU_CMD_SETADDRMODE 0X80
/**
 * [GU_SetAddrMode 设定x和y轴地址增加模式]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 */
void GU_SetAddrMode(void)
{
	GU_WriteCmd(GU_CMD_SETADDRMODE | (1 << 2) ); //x+1,y不变
}

#define GU_CMD_SET_X_STARTADDR  0X70
/**
 * [GU_Set_X_StartAddr 通过此函数可以实现水平方向移动？？]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param  addr [地址,0~127]
 */
void  GU_Set_X_StartAddr(uint8 addr)
{
	GU_WriteCmd(GU_CMD_SET_X_STARTADDR);
	GU_WriteCmd(addr);
}

#define GU_CMD_SET_Y_MOVEMODE   0XB0
// #define   GU_Y_MOVE_UP        0X08
// #define   GU_Y_MOVE_DOWN      0X00
// #define   GU_Y_MOVE_DOT1      0X04
// #define   GU_Y_MOVE_DOT2      0X06
// #define   GU_Y_MOVE_DOT8      0X02
/**
 * [GU_Y_MOVE 定义Y方向移动点数]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param moveMode [dir+dot]
 */
void GU_Y_MOVE(uint8 moveMode)
{
	GU_WriteCmd(0XB0 | moveMode);
}

/**
 * [GU_Fill  给定数据填充屏幕]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param bmp_dat [description]
 */
void GU_Fill ( uint8 bmp_dat )
{
	uint8 y, x;
	for ( y = 0; y < 8; y++ )//8行
	{
		GU_SetAddrMode();
		GU_SetPos(0, y);
		for ( x = 0; x < 128; x++ )
			GU_WriteData ( bmp_dat );
	}
}
/**
 * [GU_RecClear  在指定区域清空数据，用于局部刷新]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [version]
 * * @return   {[type]}
 * @param x0      [description]
 * @param y0      [description]
 * @param x1      [description]
 * @param y1      [description]
 * @param bmp_dat [description]
 */
void GU_RecClear ( uint8 x0, y0, x1, y1)
{
	uint8 y, x;
	for ( y = y0; y < y1; y++ )
	{
		GU_SetAddrMode();
		GU_SetPos(x0, y);
		for ( x = x0; x < x1; x++ )
			GU_WriteData ( 0 );
	}
}
/**
 * [GU_Clear  清屏]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 */
void GU_Clear ( void )
{
	uint8 y, x;
	for ( y = 0; y < 16; y++ )
	{
		GU_SetAddrMode();
		GU_SetPos(0, y);
		for ( x = 0; x < GU_X_WIDTH; x++ )
			GU_WriteData ( 0 );
	}
}

/**
 * [GU_PutStr6x8  显示6X8一组标准ASCII字符串  显示的坐标（x,y），y为页范围0～7]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param x    [起始地址]
 * @param y    [起始地址]
 * @param ch   [显示字符串地址]
 * @param mode [模式]
 */
void GU_PutStr6x8 ( uint8 x, y, uint8 ch[] , bit mode)
{
	uint8 c = 0, i = 0, j = 0;
	while ( ch[j] != '\0' )
	{
		c = ch[j] - 32;
		if ( x > 127 ) {
			x = 0;
			y++;
		}
		GU_SetPos ( x, y );
		for ( i = 0; i < 6; i++ )
			if (mode == GUNOMALCOLORMODE)
				GU_WriteData ( F6x8[c][i] );
			else
				GU_WriteData ( ~F6x8[c][i] );
		x += 6;
		j++;
	}
}

/**
 * [GU_PutStr8x16  显示8*16一组标准ASCII字符串  显示的坐标（x,y），y为页范围0～7]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param x    [起始地址]
 * @param y    [起始地址]
 * @param ch   [显示字符串地址]
 * @param mode [模式]
 */
void GU_PutStr8x16 ( uint8 x, y, uint8 ch[] , bit mode)
{
	uint8 c = 0, i = 0, j = 0;
	while ( ch[j] != '\0' )
	{
		c = ch[j] - 32;
		if ( x > 120 ) {//写到行尾了，根据字高换对应的行数
			x = 0;
			y = y + 2;
		}
		GU_SetPos ( x, y );
		for ( i = 0; i < 8; i++ )
			if (mode == GUNOMALCOLORMODE)
				GU_WriteData ( F8X16[c * 16 + i] );
			else
				GU_WriteData ( ~F8X16[c * 16 + i] );
		GU_SetPos ( x, y + 1 );
		for ( i = 0; i < 8; i++ )
			if (mode == GUNOMALCOLORMODE)
				GU_WriteData ( F8X16[c * 16 + i + 8] );
			else
				GU_WriteData ( ~F8X16[c * 16 + i + 8] );
		x += 8;
		j++;
	}
}


/**
 * [GU_PutStr20x40 20*40的字符  0-9]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param x    [起始地址]
 * @param y    [起始地址]
 * @param ch   [显示字符串地址]
 * @param mode [模式]
 */
void GU_PutStr20x40(uint8 x, y, uint8 ch[], bit mode)
{
	uint8 c = 0, i = 0, j = 0 , h = 0;
	while ( ch[j] != '\0' )
	{
		c = ch[j] - ' ';//字库是从‘SP’开始的
		if ( x > 108 ) { //写到行尾了，换行，有bug,看字高,此处未考虑y方向越界问题
			x = 0;
			y = y + 4;
		}
		for (h = 0; h < 5; h++)
		{
			GU_SetPos ( x, y + h);
			for ( i = 0; i < 20; i++ )
				if (mode == GUNOMALCOLORMODE)
					GU_WriteData ( F20X40[c * 100 + i + h * 20] );//每个字符100个字节
				else
					GU_WriteData ( ~F20X40[c * 100 + i + h * 20] );
		}
		x += 20;//下一个字右移一个字的宽度
		j++;//下一个字寻址
	}
}

/**
 * [GU_PutChinese  显示16*16点阵,主要是汉字  显示的坐标（x,y），y为页范围0～7]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param x    [起始地址]
 * @param y    [起始地址]
 * @param N    [汉字的编号]
 * @param mode [显示模式]
 */
void GU_PutChinese ( uint8 x, y, N , bit mode)
{
	uint8 wm = 0;
	unsigned int addr = 32 * N;
	GU_SetPos ( x, y );
	for ( wm = 0; wm < 16; wm++ )
	{
		if (mode == GUNOMALCOLORMODE)
			GU_WriteData ( F16x16[addr] );
		else
			GU_WriteData ( ~F16x16[addr] );
		addr += 1;
	}
	GU_SetPos ( x, y + 1 );
	for ( wm = 0; wm < 16; wm++ )
	{
		if (mode == GUNOMALCOLORMODE)
			GU_WriteData ( F16x16[addr] );
		else
			GU_WriteData ( ~F16x16[addr] );
		addr += 1;
	}
}

/**
 * [GU_Draw_BMP  显示显示BMP图片128×64起始点坐标(x,y),x的范围0～127，y为页的范围0～7]
 * * @Author wo4fisher
 * * @DateTime 2021-08-11
 * * @copyright [© 2021 wo4fisher，All rights reserved.]
 * * @license [GPL]
 * * @version [v1.0]
 * * @return   {[void]}
 * @param x0   [起始地址]
 * @param y0   [起始地址]
 * @param x1   [起始地址+width]
 * @param y1   [起始地址+height]
 * @param BMP  [图片地址]
 * @param mode [显示模式]
 */
void GU_Draw_BMP ( uint8 x0, y0, x1, y1, uint8 BMP[] , bit mode)
{
	unsigned int j = 0;
	uint8 x, y;

	if ( y1 % 8 == 0 ) y = y1 / 8;
	else y = y1 / 8 + 1;
	for ( y = y0; y < y1; y++ )
	{
		GU_SetPos ( x0, y );
		for ( x = x0; x < x1; x++ )
		{
			if (mode == GUNOMALCOLORMODE)
				GU_WriteData ( BMP[j++] );
			else
				GU_WriteData ( ~BMP[j++] );
		}
	}
}

/********************************End of File************************************/
